package update_optimize_account

import (
	"adam2/internal/model"
	"anubis-framework/pkg/io"
	"github.com/shopspring/decimal"
	"gorm.io/gorm"
	"math/big"
)

// 卖出之前更新optimize_account
type UpdateOptimizeAccountBeforeSell struct {
	db *gorm.DB
}

// 初始化
func (u *UpdateOptimizeAccountBeforeSell) Init(db *gorm.DB) {
	u.db = db
}

// 在卖出之前更新optimize_account
func (u *UpdateOptimizeAccountBeforeSell) Exec(transactionDate string) {
	io.Infoln("在卖出之前更新optimize_account")

	// 返回优化账户
	var optimizeAccountArray model.OptimizeAccountArray
	u.db.Table("optimize_account").Select("*").Order("id_ asc").Find(&optimizeAccountArray)

	for _, optimizeAccount := range optimizeAccountArray {
		// 股票资产
		var stockAssets float64 = 0

		// 计算每一个优化账户，在某一天卖股票前的收益
		var optimizeStockTransactRecordArray model.OptimizeStockTransactRecordArray
		u.db.Raw("select * from optimize_stock_transact_record t "+
			"where t.account_name = ? and t.sell_date is null and t.sell_price is null "+
			"and t.sell_amount is null",
			(*optimizeAccount).AccountName).Scan(&optimizeStockTransactRecordArray)

		for _, optimizeStockTransactRecord := range optimizeStockTransactRecordArray {
			// 开盘价
			var currentClosePrice float64 = 0
			// 股票
			u.db.Raw("select t.close_price from stock_transaction_data_all t "+
				"where t.code_ = ? and t.date_ = to_date(?, 'yyyy-mm-dd')",
				(*optimizeStockTransactRecord).StockCode, transactionDate).Scan(&currentClosePrice)

			if currentClosePrice == 0 {
				// 说明股票在这一天没有交易记录
				io.Infoln("股票[%s]在日期[%s]没有交易记录，开始查找前一个交易日的记录", optimizeStockTransactRecord.StockCode, transactionDate)

				// 如果在某一天没有开盘价，比如停牌，则查找最近一个交易日的开盘价
				u.db.Raw("select std.close_price from "+
					"(select * from stock_transaction_data_all t "+
					"where t.code_ = ? and t.date_ < to_date(?, 'yyyy-mm-dd') "+
					"order by t.date_ desc) std where rownum <= 1",
					(*optimizeStockTransactRecord).StockCode, transactionDate).Scan(&currentClosePrice)
			}

			// 计算这只股票的资产
			decimalValue := decimal.NewFromFloat(currentClosePrice)
			decimalValue = decimalValue.Mul(decimal.NewFromInt(int64(optimizeStockTransactRecord.BuyAmount)))
			res, _ := decimalValue.Float64()
			a := new(big.Rat).SetFloat64(stockAssets)
			b := new(big.Rat).SetFloat64(res)
			stockAssets, _ = new(big.Rat).Add(a, b).Float64()
		}

		// 更新optimize_account表的stock_assets、total_assets字段
		if stockAssets != 0 {
			u.db.Exec("update optimize_account t "+
				"set t.hold_stock_number=?, t.stock_assets = ?, t.total_assets = round(t.capital_assets + ?, 4) where t.account_name = ?",
				len(optimizeStockTransactRecordArray), stockAssets, stockAssets, (*optimizeAccount).AccountName)
		}
	}
}
